Skip to main content

Quick start

Welcome to PREDA-Toolchain. Before learning how to use it, please refer to the Installation Guide document to install PREDA-Toolchain.

After installing the PREDA-Toolchain, it is important to become familiar with it, including how to write a smart contract, compile the smart contract, and write a test script to test the smart contract, by going through the following contents:

  • Write a smart contract
  • Compile the smart contract
  • Write a test script to test the smart contract

Write a smart contract

There are some example smart contracts and test scripts in the installation package for learning and reference.

Next, we will take the Ballot.prd as an example to demonstrate.

Ballot.prd is a voting smart contract written in PREDA language, it implements voting in parallel on a shard blockchain, of course, we still have a lot of questions for a real practical voting system, but at least we showed how to implement voting logic through PREDA. It has the following functions:

  • Initialize proposals
  • Vote
  • Collect votes

Initialize proposals

@address function init(array<string> names) export {
//__debug.assert(controller == __transaction.get_self_address());
__debug.assert(!is_voting());
relay@global (^names){
__debug.print("global: ", names);
for (uint32 i = 0u; i < names.length(); i++) {
Proposal proposal;
proposal.name = names[i];
proposal.totalVotedWeight = 0u64;
proposals.push(proposal);
}
current_case++;
last_result.case = 0u;
last_result.topVoted = "";
}
__debug.print("EOC init: ", names);
}

A relay statement is similar to a function call, except that the call is asynchronous. The call data is packaged in a so-called "relay transaction" and relayed to the target address for execution. The relay statement itself returns immediately.

vote

@address function bool vote(uint32 proposal_index, uint32 case_num) export {
if(case_num == current_case && case_num > voted_case && proposal_index<proposals.length())
{
voted_case = case_num;
__debug.print("Vote: ", proposal_index);

/*
relay@global (^case_num, ^proposal_index, ^weight) {
if(case_num == current_case)
proposals[proposal_index].totalVotedWeight += weight;
}*/
votedWeights.set_length(proposals.length());
votedWeights[proposal_index] += weight;
return true;
}

__debug.print("Vote: ", proposal_index, " failed");
return false;
}

Collect votes

@address function finalize() export {
//__debug.assert(controller == __transaction.get_self_address());
__debug.assert(is_voting());
relay@global (){
// ... maybe do something else before scatter-gathering
__debug.print("In global");
shardGather_reset();
relay@shards (){
// ... maybe do something in each shard
__debug.print("Shard Vote: ", votedWeights);
relay@global(auto shardVotes = votedWeights) {
//BEGIN: code for scattering
for(uint32 i=0u; i<shardVotes.length(); i++)
{
proposals[i].totalVotedWeight += uint64(shardVotes[i]);
}
//END

if(shardGather_gather())
{
__debug.print("votes: ", proposals);
//BEGIN: code for gathering
last_result.case = current_case;
uint64 w = 0u64;
for(uint32 i=0u; i<proposals.length(); i++)
{
if(proposals[i].totalVotedWeight > w)
{
last_result.topVoted = proposals[i].name;
w = proposals[i].totalVotedWeight;
}
}

__debug.print("result: ", last_result);
//END
}
}
}
}
}

For more syntax details, please refer to PREDA Language Specification document.

Compile the smart contract

Right click on the contract file, select the PREDA:Compile command to compile the smart contract, this process will check the contract syntax.

image-20221208170036122

Write a test script to test the smart contract

PREDA-toolchain provides a scripting language for testing smart contracts easily, it mainly includes the following functions:

  • deploy smart contract
  • set on-chain states
  • call a smart contract function
  • smart contract performance testing
  • chain info visualization

Now we will take the Ballot.prdts as an example to demonstrate.

Write a test script

This is the code details of Ballot.prdts

// set random seed, default value is timestamp
random.reseed

// allocate some address for the test
allocate.address $~count$

// set gas limit
chain.gaslimit 256

// deploy contract
chain.deploy @1 Ballot.prd

// log
log.highlight Token test
log Perparing test transactions

// set state, prepare for the test
state.set address.Ballot @all { weight:$random(1, 20)$, voted_case:0 }

log.highlight Ballot test: Step 1

// call Ballot.init at address_0
txn1 = Ballot.init @0 { names: ["Spring", "Yarn", "Combat"] }

// run the chain
chain.run
// print chain info
chain.info

log.highlight Ballot test: Step 2
// call Ballot.vote at all address
txn2[] = Ballot.vote @all { proposal_index: $random(0,2)$, case_num: 1 }
// print chain info
chain.info

log.highlight Ballot test: Step 3
// call Ballot.finalize at address_0 to collect votes
txn3 = Ballot.finalize @0 {}

chain.info
log Executing

// start stopwatch
stopwatch.restart
// run the chain to excute transactions
chain.run
// stop stopwatch to report performance
stopwatch.report

chain.info

// address visualization
viz.addr @random
viz.addr @3 Ballot
viz.addr @all

// txn visualization
viz.txn txn1
viz.txn txn2[0]

viz.section Finalize
// trace visualization
viz.trace txn3

// profiling visualization
viz.profiling

For more syntax details, please refer to PREDA test script syntax Chapter.

Set input parameters of the test script

Right-click on the scipt file, and select PREDA:Set Args

image-20230725174253013

Enter the parameters in the pop-up box and confirm, PREDA-toolchain will execute the script with the set input parameters.

image-20230725174352424

Run the test script

Right click on the script file, and select PREDA:Run, PREDA-toolchain will execute the test script.

image-20230725174500694

Chain info visualization

The PREDA-toolchain will provide a visual interface for chain information after execute the test script.

image-20230725174712509